﻿using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace SketchUpAPI.NET.Objects
{
    /// <summary>
    /// 图像引用
    /// </summary>
    public class ImageRep : ObjectBase
    {
        #region API 函数
        /// <summary>
        /// 创建一个 <see cref="ImageRep"/>
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepCreate(ref IntPtr image);

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepRelease(ref IntPtr image);

        /// <summary>
        /// 从 <paramref name="copy_image"/> 拷贝数据到 <paramref name="image"/> 中
        /// </summary>
        /// <param name="image"><see cref="ImageRep"/> 接收数据的图像</param>
        /// <param name="copy_image"><see cref="ImageRep"/> 被拷贝数据的图像</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepCopy(IntPtr image, IntPtr copy_image);

        /// <summary>
        /// 设置图片数据
        /// </summary>
        /// <param name="image"></param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="bits_per_pixel">每个像素位深度，8、24、32</param>
        /// <param name="row_padding">每行个数</param>
        /// <param name="pixel_data">图像数据</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepSetData(IntPtr image, long width, long height, long bits_per_pixel, long row_padding, byte[] pixel_data);

        /// <summary>
        /// 从图片文件中加载数据
        /// </summary>
        /// <param name="image"></param>
        /// <param name="file_path">图片路径</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepLoadFile(IntPtr image, [MarshalAs(UnmanagedType.LPUTF8Str)] string file_path);

        /// <summary>
        /// 保存数据到图片文件
        /// </summary>
        /// <param name="image"></param>
        /// <param name=""></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepSaveToFile(IntPtr image, [MarshalAs(UnmanagedType.LPUTF8Str)] string file_path);

        /// <summary>
        /// 获取图像的宽高
        /// </summary>
        /// <param name="image"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetPixelDimensions(IntPtr image, out long width, out long height);

        /// <summary>
        /// 获取图像行填充大小
        /// </summary>
        /// <param name="image"></param>
        /// <param name="row_padding"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetRowPadding(IntPtr image, out long row_padding);

        /// <summary>
        /// 设置图像的宽高
        /// </summary>
        /// <param name="image"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepResize(IntPtr image, long width, long height);

        /// <summary>
        /// 转换位32位深度
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepConvertTo32BitsPerPixel(IntPtr image);

        /// <summary>
        /// 获取图像的总大小和每个像素的位数。
        /// </summary>
        /// <remarks>该方法用于确定调用 SUImageRepGetData 方法时传递的数据</remarks>
        /// <param name="image"></param>
        /// <param name="data_size"></param>
        /// <param name="bits_per_pixel"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetDataSize(IntPtr image, out long data_size, out long bits_per_pixel);

        /// <summary>
        /// 获取图像数据
        /// </summary>
        /// <param name="image"></param>
        /// <param name="data_size">总大小</param>
        /// <param name="pixel_data">保存数据</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetData(IntPtr image, long data_size, byte[] pixel_data);

        /// <summary>
        /// 获取图像的颜色
        /// </summary>
        /// <param name="image"></param>
        /// <param name="color_data">保存全部颜色</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetDataAsColors(IntPtr image, Color[] color_data);

        /// <summary>
        /// 获取某点的颜色
        /// </summary>
        /// <param name="image"></param>
        /// <param name="u"></param>
        /// <param name="v"></param>
        /// <param name="bilinear">是否使用双线性纹理过滤。这会对颜色进行插值，而不是获取最近的。</param>
        /// <param name="color"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUImageRepGetColorAtUV(IntPtr image, double u, double v, bool bilinear, ref Color color);
        #endregion

        public ImageRep()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepCreate(ref Id));
        }

        internal ImageRep(IntPtr id) => Id = id;

        /// <summary>
        /// 从图片文件加载数据
        /// </summary>
        /// <param name="path"></param>
        public void LoadFromFile(string path)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepLoadFile(Id, path));
        }

        /// <summary>
        /// 将图像保存位文件
        /// </summary>
        /// <param name="path"></param>
        public void SaveToFile(string path)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepSaveToFile(Id, path));
        }

        /// <summary>
        /// 从另一个图像复制数据
        /// </summary>
        /// <param name="other"></param>
        public void CopyFrom(ImageRep other)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepCopy(Id, other.Id));
        }

        /// <summary>
        /// 设置图像数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="bits_per_pixel"></param>
        /// <param name="row_padding"></param>
        public void SetData(byte[] data, long width, long height, long bits_per_pixel, long row_padding)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepSetData(Id, width, height, bits_per_pixel, row_padding, data));
        }

        /// <summary>
        /// 获取图像数据
        /// </summary>
        /// <param name="data">返回每个像素的颜色，顺序是：B、G、R、A</param>
        public byte[] GetData()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepGetDataSize(Id, out long data_size, out _));

            var data = new byte[data_size];
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepGetData(Id, data_size, data));
            return data;
        }

        /// <summary>
        /// 以 <see cref="Color"/>二维数组 的形式获取图像数据
        /// </summary>
        /// <param name="colors"></param>
        public Color[,] GetDataAsColors()
        {
            GetSize(out long width, out long height); // 5  5
            GetRowPadding(out long padding);
            byte[] data = GetData(); // 每个像素的 BGRA
            Color[,] colors = new Color[height, width];

            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    long index = (row * (width + padding) + col) * 4;
                    byte b = data[index];
                    byte g = data[index + 1];
                    byte r = data[index + 2];
                    byte a = data[index + 3];

                    colors[row, col] = new Color(r, g, b, a);
                }
            }

            return colors;
        }

        /// <summary>
        /// 获取某个UV点对应的颜色
        /// </summary>
        /// <param name="u"></param>
        /// <param name="v"></param>
        /// <param name="bilinear">是否使用双线性滤波插值</param>
        /// <returns></returns>
        public Color GetColorAtUV(long u, long v, bool bilinear)
        {
            Color c = new Color();
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepGetColorAtUV(Id, u, v, bilinear, ref c));
            return c;
        }

        /// <summary>
        /// 获取图像尺寸
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void GetSize(out long width, out long height)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepGetPixelDimensions(Id, out width, out height));
        }

        /// <summary>
        /// 设置图像尺寸
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void Resize(long width, long height)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepResize(Id, width, height));
        }

        /// <summary>
        /// 将图像装换为32位深度
        /// </summary>
        public void To32Bit()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepConvertTo32BitsPerPixel(Id));
        }

        /// <summary>
        /// 获取每行最后留空的数据个数
        /// </summary>
        /// <param name="rowPadding"></param>
        public void GetRowPadding(out long rowPadding)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepGetRowPadding(Id, out rowPadding));
        }

        public override void Dispose()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUImageRepRelease(ref Id));
        }
    }
}